#ifndef _MODBUS_H
#define _MODBUS_H

#define MODBUS_SPEED        9600
#define MODBUS_PDU_LEN      64+12
#define MODBUS_TIMEOUT      ((3.5*11/MODBUS_SPEED) * 1000 + 1)
#define MODBUS_DIR_SETUP    ((0.5*11/MODBUS_SPEED) * 1000000)
#define MODBUS_DIR_HOLD     ((0.5*11/MODBUS_SPEED) * 1000000)

#define MODBUS_DIR          PD2
#define MODBUS_DIR_DDR      DDRD
#define MODBUS_DIR_PORT     PORTD


#if defined(__AVR_ATmega8__)  || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  #define UART_STATUS       UCSRA
  #define UART_DATA         UDR

#elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  #define USART_RX_vect     USART0_RX_vect
  #define UART_STATUS       UCSR0A
  #define UART_DATA         UDR0
  #define TXC               TXC0

#endif


#define MODBUS_READ_COILS                   1
#define MODBUS_READ_DISCRETE_INPUTS         2
#define MODBUS_WRITE_SINGLE_COIL            5
#define MODBUS_WRITE_MULTIPLE_COILS         15
#define MODBUS_READ_HOLDING_REGISTER        3
#define MODBUS_READ_INPUT_REGISTER          4
#define MODBUS_WRITE_REGISTER               6
#define MODBUS_WRITE_MULTIPLE_REGISTERS     16
#define MODBUS_READWRITE_MULTIPLE_REGISTERS 23
#define MODBUS_READ_FILE_RECORD             20
#define MODBUS_WRITE_FILE_RECORD            21
#define MODBUS_DIAGNOSTIC                   8
#define MODBUS_ERROR                        128

#define MODBUS_ERR_NONE                     0x00
#define MODBUS_ERR_ILLEGAL_FUNCTION         0x01
#define MODBUS_ERR_ILLEGAL_DATA_ADDRESS     0x02
#define MODBUS_ERR_ILLEGAL_DATA_VALUE       0x03
#define MODBUS_ERR_SLAVE_DEVICE_FAILURE     0x04
#define MODBUS_ERR_ACKNOWLEDGE              0x05
#define MODBUS_ERR_SLAVE_BUSY               0x06
#define MODBUS_ERR_MEMORY_PARITY_ERROR      0x08


typedef bool(*MODBUS_HANDLER)(uint8_t, uint8_t*, uint8_t, bool);

extern void modbus_init(uint8_t address, MODBUS_HANDLER handler);
extern void modbus_task(void);
extern void modbus_send(uint8_t function, uint8_t *data, uint8_t length);


#endif
